package com.binarysoft.cmdhandler.common.snmp;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;

import com.binarysoft.service.common.snmp.SnmpObject;
import com.binarysoft.service.common.snmp.SnmpResult;
import com.binarysoft.service.common.snmp.SnmpService;
import com.binarysoft.service.common.snmp.SnmpTarget;
import com.binarysoft.service.common.snmp.SnmpTool;
import com.binarysoft.service.common.snmp.SnmpValue;

import common.framework.command.handler.AbstractCommandHandler;
import common.framework.command.helper.CommandHelper;
import common.framework.command.server.CommandException;
import common.framework.command.server.Terminal;
import common.framework.dsb.annotation.DSBCmd;
import common.framework.dsb.client.DefaultServiceFactory;
import common.framework.dsb.client.ServiceFactory;

@DSBCmd("snmp")
public class SnmpCmdHandler extends AbstractCommandHandler {

	private String community = "public";
	private String version = "2";
	private String address = null;

	// snmp version 3
	private String userName;
	private String sSecurityLevel;
	private String sAuthProtocol;
	private String authPassword;
	private String sPrivProtocol;
	private String privatePassword;

	public void close() {

	}

	/**
	 * 命令执行的主方法
	 */
	public void handle(String args, Terminal terminal) throws Exception {
		terminal.println("");
		StringTokenizer stier = new StringTokenizer(args);
		int count = stier.countTokens();
		if (count < 5) {
			showHelp(terminal);
			return;
		}

		ServiceFactory serviceFactory = new DefaultServiceFactory();
		stier.nextToken();// snmp
		// get,getnext,walk
		String cmd = stier.nextToken();
		if ("get".equalsIgnoreCase(cmd)) {
			String opt = null;
			do {
				opt = stier.nextToken(); // -c -v -t -r
				readOptions(stier, opt);
			} while (opt.indexOf("-") > -1);
			this.address = opt;
			String oid = stier.nextToken();
			// snmp service
			SnmpService snmpService = serviceFactory.lookup("DSB/SnmpService");
			SnmpTarget snmpTarget = this.createSnmpTarget();
			SnmpObject snmpObject = new SnmpObject();
			snmpObject.setName("undefined");
			// 关闭DefaultIndexValue，直接采用用户输入的OID进行snmp get操作
			snmpObject.setUseDefaultIndex(false);
			snmpObject.setOid(oid);
			snmpObject.setObjectType(SnmpService.SINGLE_INSTANCE_OBJECT);
			SnmpResult snmpResult = snmpService.snmpGet(snmpObject, snmpTarget);
			printSnmpResult(snmpResult, terminal);

		} else if ("getnext".equalsIgnoreCase(cmd)) {
			String opt = null;
			do {
				opt = stier.nextToken(); // -c -v -t -r
				readOptions(stier, opt);
			} while (opt.indexOf("-") > -1);
			this.address = opt;
			String oid = stier.nextToken();
			// snmp service
			SnmpService snmpService = serviceFactory.lookup("DSB/SnmpService");
			SnmpTarget snmpTarget = this.createSnmpTarget();
			SnmpObject snmpObject = new SnmpObject();
			snmpObject.setName("undefined");
			snmpObject.setOid(oid);
			snmpObject.setObjectType(SnmpService.MULTI_INSTANCE_OBJECT_WITHOUT_INDEX);
			SnmpResult snmpResult = snmpService.snmpGet(snmpObject, snmpTarget);
			printSnmpResult(snmpResult, terminal);

		} else {
			showHelp(terminal);
			return;
		}
		terminal.println("");

	}

	private void printSnmpResult(SnmpResult snmpResult, Terminal terminal) throws Exception {
		String[] tableHAD = { "OID", "Index", "Value" };
		String[] tableGAP = { "---", "-----", "-----" };
		int[] format = { 30, 15, 10 };
		terminal.println(CommandHelper.format(tableHAD, format));
		terminal.println(CommandHelper.format(tableGAP, format));
		Iterator<SnmpValue> values = snmpResult.iterator();
		while (values.hasNext()) {
			SnmpValue value = values.next();
			String val = SnmpTool.convertString(value.getValue().toString().trim(), "gb2312");
			Object[] row = { value.getOid(), value.getIndex(), val };
			terminal.println(CommandHelper.format(row, format));
		}
	}

	private void readOptions(StringTokenizer stier, String currentOpt) throws Exception {
		if (currentOpt.equals("-v")) {
			this.version = stier.nextToken();
		} else if (currentOpt.equals("-c")) {
			this.community = stier.nextToken();
		}
	}

	private SnmpTarget createSnmpTarget() throws Exception {
		SnmpTarget snmpTarget = new SnmpTarget();
		snmpTarget.setHostAddress(this.address);
		snmpTarget.setSnmpPort(161);
		if ("1".equalsIgnoreCase(this.version)) {
			snmpTarget.setSnmpVersion(SnmpService.VERSION1);
			snmpTarget.setReadCommunity(this.community);
		} else if ("2".equalsIgnoreCase(this.version)) {
			snmpTarget.setSnmpVersion(SnmpService.VERSION2C);
			snmpTarget.setReadCommunity(this.community);
		} else if ("3".equalsIgnoreCase(this.version)) {
			snmpTarget.setSnmpVersion(SnmpService.VERSION3);
			snmpTarget.setUserName(this.userName);
			int securityLevel = Integer.parseInt(sSecurityLevel);
			snmpTarget.setSecurityLevel(securityLevel);
			if (SnmpService.AUTH_NOPRIV == securityLevel) {
				int authProtocol = Integer.parseInt(sAuthProtocol);
				snmpTarget.setAuthProtocol(authProtocol);
				snmpTarget.setAuthPassword(authPassword);
			} else if (SnmpService.AUTH_PRIV == securityLevel) {
				int authProtocol = Integer.parseInt(sAuthProtocol);
				snmpTarget.setAuthProtocol(authProtocol);
				snmpTarget.setAuthPassword(authPassword);
				int privProtocol = Integer.parseInt(sPrivProtocol);
				snmpTarget.setPrivProtocol(privProtocol);
				snmpTarget.setPrivatePassword(privatePassword);
			} else if (SnmpService.NOAUTH_NOPRIV == securityLevel) {
				// to do nothing.
			}
		}
		return snmpTarget;
	}

	/**
	 * 显示命令的使用方法和格式
	 * 
	 * @param terminal
	 *            输出流
	 * @throws CommandException
	 *             命令的意外错误
	 * @throws IOException
	 *             如果无法连接
	 */
	private void showHelp(Terminal terminal) throws CommandException, IOException {
		terminal.println("usage: snmp get     [options] agent [oid]");
		terminal.println("       snmp getnext [options] agent [oid]");
		terminal.println("");
		terminal.println("options:");
		terminal.println("-c community          snmp community string(only for v1 and v2c)");
		terminal.println("-v 1|2                snmp version");
		terminal.println("agent: the target snmp agent address");
		terminal.println("oid: the snmp OID");
		terminal.println("");
	}

	public void setConfig(Map<String, String> arg0) throws CommandException {

	}

}
